﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using Pixysoft.Framework.Security.Controller;
using Pixysoft.Tools;
using Pixysoft.Framework.Logs;
using Pixysoft.Framework.Security.WebAuth;
using System.Text.RegularExpressions;
using Pixysoft.Framework.Security.Entity;

namespace Pixysoft.Framework.Security
{
    /// <summary>
    /// 登录用户 行为日志
    /// ip/url/time/referer/usernmae
    /// </summary>
    class WebsiteLogModule : ExceptionModule, IHttpModule
    {
        public override void Init(HttpApplication context)
        {
            base.Init(context);

            context.AcquireRequestState += new EventHandler(context_AcquireRequestState);
        }

        void context_AcquireRequestState(object sender, EventArgs e)
        {
            HttpApplication app = (HttpApplication)sender;

            HttpRequest req = app.Request;

            bool isSkip = CanSkipIt(app);//！！！！速度中，需要全部执行

            if (isSkip)//快
            {
                return;
            }

            string url = req.Url.ToString();

            string param = this.GetParamValue(req);

            LoggerHelper.Debug("begin website log page");

            LoggerHelper.Debug("log.url:{0}", url);

            LoggerHelper.Debug("log.param:{0}", param);


            if (IsSkipRequest(app, req))
            {
                return;
            }

            if (Pixysoft.Web.UrlHelper.Instance.IsPostBack(req))//快
            {
                return;
            }

            string token = Pixysoft.Web.CookieHelper.Instance.ExtractTokenFromCookie(req, StringHelper.cookieName_userinfo);

            if (string.IsNullOrEmpty(token))
            {
                if (SettingHelper.Instance.LogAnonymous)
                    LogNonLogin(req);

                return;
            }

            UserInfo userProfile = WebAuthController.GetUserInfo(token);

            if (userProfile == null)
            {
                if (SettingHelper.Instance.LogAnonymous)
                    LogNonLogin(req);

                return;
            }
            else
            {
                LogLogin(req, userProfile);
            }
        }

        private bool IsSkipRequest(HttpApplication app, HttpRequest request)
        {
            object[] ress = app.Context.Handler.GetType().GetCustomAttributes(typeof(LogSkipPageAttribute), true);

            if (ress != null && ress.Length > 0)
                return true;

            foreach (string key in request.QueryString.AllKeys)
            {
                if (string.IsNullOrEmpty(key))
                    continue;

                if (string.IsNullOrEmpty(Regex.Replace(key, StringHelper.skipRequestExts, "", RegexOptions.IgnoreCase)))
                    return true;
            }
            return false;
        }

        private string GetParamValue(HttpRequest req)
        {
            StringBuilder builder = new StringBuilder();

            foreach (string key in req.QueryString.Keys)
            {
                if (string.IsNullOrEmpty(key))
                    continue;

                builder.Append(key).Append(":").AppendLine(req.QueryString[key]);
            }

            foreach (string key in req.Form.Keys)
            {
                if (string.IsNullOrEmpty(key))
                    continue;

                builder.Append(key).Append(":").AppendLine(req.Form[key]);
            }

            return builder.ToString();
        }

        private void LogLogin(HttpRequest req, UserInfo userProfile)
        {
            string ip = req.UserHostAddress;
            string referer = req.UrlReferrer == null ? "localhost" : req.UrlReferrer.AbsoluteUri;
            string url = req.Url.AbsolutePath;
            long time = GlobalTimer.Instance.GetGlobalTime().Ticks;
            string loginName = userProfile.Name;

            Logging(ip, referer, url, time, loginName);
        }

        private void LogNonLogin(HttpRequest req)
        {
            string ip = req.UserHostAddress;
            string referer = req.UrlReferrer == null ? "localhost" : req.UrlReferrer.AbsoluteUri;
            string url = req.Url.AbsolutePath;
            long time = GlobalTimer.Instance.GetGlobalTime().Ticks;

            Logging(ip, referer, url, time, null);
        }

        private void Logging(string ip, string referer, string url, long time, string loginName)
        {
            referer = referer.Replace(";", "::");

            if (!string.IsNullOrEmpty(loginName))
                loginName = loginName.Replace(";", "::");

            ILogger logger = Logger.GetLogger(StringHelper.default_log_webstie);

            logger.All("{0};{1};{2};{3};{4};", ip, referer, url, time, loginName);
        }
    }
}
